/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package productions;

import exceptions.ParserException;
import java.util.ArrayList;
import lexico.ErrorTable;
import lexico.SymbolTable;
import lexico.TokenClass;
import sintatico.ErrorTableParser;

/**
 *
 * @author eder e caco
 */
public abstract class AbstractProductionRule {

    protected ArrayList<TokenClass> first  = new ArrayList<TokenClass>();
    protected ArrayList<TokenClass> follow = new ArrayList<TokenClass>();
    protected ArrayList<TokenClass> sync   = new ArrayList<TokenClass>();
//    protected SymbolTable st;
//    protected ErrorTableParser etp;


    
    protected AbstractProductionRule() {
        this.populateFirst();
        this.populateFollow();
        this.populateSync();
    }

 
    /**
     * Verifica se o TokenClass passado é igual ao do token atual,
     * e já consome o token atual.
     * @param c
     * @return
     */
    protected boolean basicParse(SymbolTable st, TokenClass c) {
        if (basicTest(st, c)) {
            st.consumeCurrent();
            return true;
        }
        return false;
    }

    /**
     * Compara se o TokenClass passado é igual ao do token atual.
     * @param c
     * @return
     */
    protected boolean basicTest(SymbolTable st, TokenClass c) {
        if (!st.eof() && c == st.getCurrent().getTokenClass()) {
            return true;
        }
        return false;
    }

    /**
     * Realiza um parsing básico para as produções que só têm terminais.
     * @return
     */
    protected boolean basicTerminalParsing(SymbolTable st) {
        if (!st.eof() && isFirst(st.getCurrent().getTokenClass())) {
            st.consumeCurrent();
            return true;
        }
        return false;
    }

    /**
     * Realiza a analise sintatica para a determinada regra
     *
     * @param st a tabela de simbolos
     * @param et a tabela de erros
     * @return true se a sequencia foi reconhecida, falso caso contrario
     */
    public abstract boolean analyze(SymbolTable st, ErrorTable et) throws ParserException;


    /**
     * Popula o conjunto primeiro da regra.
     *
     */
    protected abstract void populateFirst();

    /**
     * Popula o conjunto seguinte da regra.
     *
     */
    protected abstract void populateFollow();

    /**
     * Popula o conjunto de sincronizacao
     *
     */
    protected void populateSync(){
         sync = follow;
    }

    /**
     * Informa se <code>tclass</code> esta no conjunto primeiro da regra
     * @param tclass um TokenClass
     * @return true se sim, falso caso contrario
     */
    public boolean isFirst(TokenClass tclass) {
        return first.contains(tclass);
    }

    /**
     * Informa se <code>tclass</code> esta no conjunto seguinte da regra
     * @param tclass um TokenClass
     * @return true se sim, falso caso contrario
     */
    public boolean isFollow(TokenClass tclass) {
        return follow.contains(tclass);
    }

    /**
     * Informa se <code>tclass</code> esta no conjunto de sincronizacao da regra
     * @param tclass um TokenClass
     * @return true se sim, falso caso contrario
     */
    public boolean isSynchronizer(TokenClass tclass) {
        return sync.contains(tclass);
    }



    /**
     * Pula os tokens ate chegar em um token do conjunto de sincronizacao,
     * alem de adicionar uma mensagem de erro relevante
     * @param st
     */
    protected boolean skipUntilSynchronize(SymbolTable st, ErrorTable et, String message){

        et.addError(st, message);

        while(!st.eof() && !isSynchronizer(st.getCurrent().getTokenClass()) ){
            st.consumeCurrent();
        }

        return true;
    }


    




    

}
